package main

import (
	"fmt"
	"reflect"
)

func declarePoint() {
	var aa int = 20 /* 声明实际变量 */
	var ip *int     /* 声明指针变量 */
	ip = &aa        /* 指针变量的存储地址 */
	fmt.Printf("aa 变量的地址是: %x\n", &aa)
	/* 指针变量的存储地址 */
	fmt.Printf("ip 变量的存储地址: %x\n", ip)
	/* 使用指针访问值 */
	fmt.Printf("*ip 变量的值: %d\n", *ip)
}

func declarePointStruct() {
	type data struct{ a int }

	var d = data{a: 1234}
	var p *data

	p = &d
	fmt.Printf("%p, %v\n", p, p.a) // 直接用指针访问目标对象成员，无须转换。
}

func pointReturn(v int) *int {
	newVal := v * 10
	return &newVal
}

func main() {

	a := 1                                                        // 定义一个变量a，并赋值为1
	b := &a                                                       // 通过取地址符取出变量a在内存中的地址， b的类型是*int,b是指向a的盒子，*b就可以拿到里面的东西了
	fmt.Println("b的类型是", reflect.TypeOf(b), "b的值是", b, "*b是", *b) // 打印取出的地址
	c := *b                                                       // 指针类型前面加上*， 就可以获取指针类型的值
	fmt.Println("c的值:", c)

	d := &b // d的类型是**int, d是指向b的盒子， d本身是指针，它存的东西也是指针
	fmt.Println("d的值是", d, "*d是", *d, "**d是", **d)

	m := 1
	n := 2
	f1 := addF
	f1(&m, &n)
	f1p1 := &f1 // 函数的指针
	(*f1p1)(&m, &n)

	// 定义指针,
	var age int = 18
	var ptr *int = &age
	fmt.Println(&age) // 得到的是，地址
	fmt.Println(ptr)  // 得到的也是同上，地址
	fmt.Println("ptr本身这个存储空间的地址为", &ptr)
	fmt.Println("ptr指向的数值为 %v", *ptr)

	// *地址：获取到的是值
	// var ptr *int = 【&age】必须是个地址，如果写成age报错
	// var age int = 18， age是int类型，如果var ptr *float32 = &age也是异常

	//使用new进行初始化
	var point = new(int)
	*point = 1
	fmt.Printf("a的值：%d \n", *point)
	fmt.Printf("a的类型：%T \n", point)

	var num *int // 定义一个int类型的指针
	*num++       // 程序会自动退出

	o := Opt{
		n1: 1,
		n2: 2,
	}
	fmt.Println("struct opt 操作前: %p:", &o)
	add(&o)
	fmt.Println("struct opt 操作后: %p", &o)

}
func addF(n1, n2 *int) {
	*n1 = *n1 + *n2
}

type Opt struct {
	n1     int
	n2     int
	result int
}

func add(p *Opt) {
	p.result = p.n1 + p.n2
}
